from datetime import datetime, timedelta
import unittest
from microblog.app import db, app
from microblog.app.models import User, Post, Follow

class UserModelCase(unittest.TestCase):
    def setUp(self) -> None:
        #use memory sqlite dadabase
        app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
        db.create_all()

    def tearDown(self) -> None:
        db.session.remove()
        db.drop_all()

    def test_password_hashing(self):
        u = User(username='susan', email='susan.exp.com')
        u.set_password('cat')
        self.assertFalse(u.check_password('dog'))
        self.assertTrue(u.check_password('cat'))

    def test_follow(self):
        u1 = User(username='susan', email='susan@exp.com')
        u2 = User(username='neo', email='neo@exp.com')
        db.session.add(u1)
        db.session.add(u2)
        db.session.commit()
        self.assertEqual(u1.followed().all(), [])
        self.assertEqual(u2.followed().all(), [])

        u1.follow(u2.id)
        db.session.commit()
        self.assertTrue(u1.is_following(u2.id))
        self.assertFalse(u2.is_following(u1.id))
        self.assertEqual(u1.followed().count(), 1)
        self.assertEqual(u2.followed().count(), 0)
        self.assertEqual(u1.followed().first().username, u2.username)
        self.assertEqual(u2.follower().count(), 1)
        self.assertEqual(u1.follower().count(), 0)
        self.assertEqual(u2.follower().first().username, u1.username)

        u1.unfollow(u2.id)
        db.session.commit()
        self.assertEqual(u1.followed().count(), 0)
        self.assertEqual(u2.follower().count(), 0)

    def test_follow_posts(self):
        u1 = User(username='susan', email='susan@exp.com')
        u2 = User(username='neo', email='neo@exp.com')
        u3 = User(username='john', email='john@exp.com')
        u4 = User(username='alex', email='alex@exp.com')
        db.session.add_all([u1, u2, u3, u4])
        db.session.commit()

        ff1 = u1.followed_posts().all()
        self.assertEqual(ff1, [])

        now = datetime.utcnow()
        p1 = Post(body='post#1 from susan', user_id=u1.id, timestamp=now+timedelta(seconds=1))
        p2 = Post(body='post#1 from neo', user_id=u2.id, timestamp=now+timedelta(seconds=2))
        p3 = Post(body='post#1 from john', user_id=u3.id, timestamp=now+timedelta(seconds=3))
        p4 = Post(body='post#1 from alex', user_id=u4.id, timestamp=now+timedelta(seconds=4))
        db.session.add_all([p1, p2, p3, p4])
        db.session.commit()

        self.assertEqual(p1.author(), u1)
        self.assertEqual(p2.author(), u2)
        self.assertEqual(p3.author(), u3)
        self.assertEqual(p4.author(), u4)

        self.assertFalse(u1.is_following(u2.id))
        u1.follow(u2.id)
        self.assertTrue(u1.is_following(u2.id))
        self.assertFalse(u1.is_following(u3.id))
        u1.follow(u3.id)
        self.assertTrue(u1.is_following(u3.id))
        self.assertFalse(u1.is_following(u4.id))
        u1.follow(u4.id)
        self.assertTrue(u1.is_following(u4.id))

        self.assertFalse(u2.is_following(u3.id))
        u2.follow(u3.id)
        self.assertTrue(u2.is_following(u3.id))
        self.assertFalse(u2.is_following(u4.id))
        u2.follow(u4.id)
        self.assertTrue(u2.is_following(u4.id))

        self.assertFalse(u3.is_following(u4.id))
        u3.follow(u4.id)
        self.assertTrue(u3.is_following(u4.id))

        f1 = u1.followed_posts().all()
        self.assertEqual(f1, [p4, p3, p2, p1])

        f2 = u2.followed_posts().all()
        self.assertEqual(f2, [p4, p3, p2])

        f3 = u3.followed_posts().all()
        self.assertEqual(f3, [p4, p3])

        f4 = u4.followed_posts().all()
        self.assertEqual(f4, [p4])

        self.assertFalse(u4.is_following(u4.id))
        u4.follow(u4.id)
        self.assertTrue(u4.is_following(u4.id))

        f4 = u4.followed_posts().all()
        self.assertEqual(f4, [p4])

if __name__ == '__main__':
    unittest.main(verbosity=2)